package org.example.mall.admin.util;

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import org.example.mall.admin.configuration.auth.CustomUser;
import org.example.mall.admin.model.entity.manage.AccountAuth;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;

/**
 * @author hzq
 * @date 2021/12/8 13:20
 */
public class SecurityUtil {

    /**
     * 加密秘钥
     */
    public static final byte[] ENCODE_KEY = "_ENCODE__SECRET_".getBytes();
    public static final AES AES = new AES(Mode.CFB, Padding.NoPadding, new SecretKeySpec(ENCODE_KEY, "AES"), new IvParameterSpec(ENCODE_KEY));
    public static final PasswordEncoder PASSWORD_ENCODER = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    /**
     * 系统用户名
     * 用于确定用户的登录方式
     *
     * @return unionId:authType
     */
    public static String createUnionUsername(AccountAuth auth) {
        // efeaf7c0-0f10-4421-9ab5-56197d7f221c:username
        // efeaf7c0-0f10-4421-9ab5-56197d7f221c:phone
        // efeaf7c0-0f10-4421-9ab5-56197d7f221c:email
        // efeaf7c0-0f10-4421-9ab5-56197d7f221c:wx_mini_app
        return auth.getUnionId() + StringPool.COLON + auth.getAuthType();
    }

    /**
     * @param unionUsername unionId:authType
     * @return [unionId, authType]
     */
    public static String[] splitUnionUsername(String unionUsername) {
        String[] split = unionUsername.split(StringPool.COLON);
        UUID.fromString(split[0]);
        return split;
    }

    /**
     * @return 获取认证信息
     */
    public static CustomUser getCustomUser() {
        Authentication authentication = getAuthentication();

        if (authentication == null) {
            return null;
        }

        if (authentication.getPrincipal() instanceof CustomUser) {
            return (CustomUser) authentication.getPrincipal();
        }
        return null;
    }

    /**
     * @return 获取认证详情
     */
    public static AccountAuth getAuth() {
        CustomUser customUser = getCustomUser();
        if (customUser == null) {
            throw new AuthenticationCredentialsNotFoundException("未认证");
        }
        return customUser.getAuth();
    }

    /**
     * 是否已认证
     *
     * @return true 已认证 false 未认证
     */
    public static boolean verified() {
        return getCustomUser() != null;
    }

    /**
     * @return 获取用户权限列表
     */
    public static Collection<GrantedAuthority> getGrantedAuthority() {
        CustomUser customUser = getCustomUser();
        if (customUser == null) {
            return AuthorityUtils.NO_AUTHORITIES;
        }
        return customUser.getAuthorities();
    }

    /**
     * @return 认证信息
     */
    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 获取客户端
     *
     * @return clientId
     */
    public static String getClientId() {

        Authentication authentication = getAuthentication();

        // 已认证 从认证信息里面提取
        if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication auth2Authentication = (OAuth2Authentication) authentication;
            return auth2Authentication.getOAuth2Request().getClientId();
        }

        // 登录或刷新 从请求头中提取
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            BasicAuthenticationConverter basicAuthenticationConverter = new BasicAuthenticationConverter();
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = basicAuthenticationConverter.convert(getHttpServletRequest());
            if (usernamePasswordAuthenticationToken != null) {
                return usernamePasswordAuthenticationToken.getName();
            }
        }
        return null;
    }

    /**
     * @return 获取当前请求 request
     */
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }

}
